{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "51035651-6755-403d-84a0-541a77e9d995",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Package                   Version        Editable project location\n",
      "------------------------- -------------- -------------------------\n",
      "accelerate                0.30.1\n",
      "aiofiles                  23.2.1\n",
      "aiohttp                   3.9.5\n",
      "aiosignal                 1.3.1\n",
      "altair                    5.3.0\n",
      "annotated-types           0.7.0\n",
      "anyio                     4.3.0\n",
      "argon2-cffi               23.1.0\n",
      "argon2-cffi-bindings      21.2.0\n",
      "arrow                     1.3.0\n",
      "asttokens                 2.4.1\n",
      "async-lru                 2.0.4\n",
      "async-timeout             4.0.3\n",
      "attrs                     23.2.0\n",
      "Babel                     2.15.0\n",
      "beautifulsoup4            4.12.3\n",
      "bitsandbytes              0.43.1\n",
      "bleach                    6.1.0\n",
      "blinker                   1.8.2\n",
      "cachetools                5.3.3\n",
      "certifi                   2024.2.2\n",
      "cffi                      1.16.0\n",
      "chardet                   3.0.4\n",
      "charset-normalizer        3.3.2\n",
      "click                     8.1.7\n",
      "colorama                  0.4.6\n",
      "comm                      0.2.2\n",
      "contourpy                 1.2.1\n",
      "cycler                    0.12.1\n",
      "dataclasses-json          0.6.6\n",
      "datasets                  2.19.1\n",
      "debugpy                   1.8.1\n",
      "decorator                 5.1.1\n",
      "defusedxml                0.7.1\n",
      "dill                      0.3.8\n",
      "distro                    1.9.0\n",
      "dnspython                 2.6.1\n",
      "docstring_parser          0.16\n",
      "einops                    0.8.0\n",
      "email_validator           2.1.1\n",
      "exceptiongroup            1.2.1\n",
      "executing                 2.0.1\n",
      "fastapi                   0.111.0\n",
      "fastapi-cli               0.0.4\n",
      "fastjsonschema            2.19.1\n",
      "ffmpy                     0.3.2\n",
      "filelock                  3.13.1\n",
      "fire                      0.6.0\n",
      "fonttools                 4.51.0\n",
      "fqdn                      1.5.1\n",
      "frozenlist                1.4.1\n",
      "fsspec                    2024.2.0\n",
      "gitdb                     4.0.11\n",
      "GitPython                 3.1.43\n",
      "googletrans               3.0.0\n",
      "gradio                    4.36.0\n",
      "gradio_client             1.0.1\n",
      "greenlet                  3.0.3\n",
      "h11                       0.14.0\n",
      "h2                        3.2.0\n",
      "hpack                     3.0.0\n",
      "hstspreload               2024.6.1\n",
      "httpcore                  1.0.5\n",
      "httptools                 0.6.1\n",
      "httpx                     0.27.0\n",
      "huggingface-hub           0.23.1\n",
      "hyperframe                5.2.0\n",
      "idna                      2.10\n",
      "importlib_resources       6.4.0\n",
      "intel-openmp              2021.4.0\n",
      "ipykernel                 6.29.4\n",
      "ipython                   8.25.0\n",
      "ipywidgets                8.1.3\n",
      "isoduration               20.11.0\n",
      "jedi                      0.19.1\n",
      "jieba                     0.42.1\n",
      "Jinja2                    3.1.3\n",
      "joblib                    1.4.2\n",
      "json5                     0.9.25\n",
      "jsonpatch                 1.33\n",
      "jsonpointer               2.4\n",
      "jsonschema                4.22.0\n",
      "jsonschema-specifications 2023.12.1\n",
      "jupyter                   1.0.0\n",
      "jupyter_client            8.6.2\n",
      "jupyter-console           6.6.3\n",
      "jupyter_core              5.7.2\n",
      "jupyter-events            0.10.0\n",
      "jupyter-lsp               2.2.5\n",
      "jupyter_server            2.14.1\n",
      "jupyter_server_terminals  0.5.3\n",
      "jupyterlab                4.2.2\n",
      "jupyterlab_pygments       0.3.0\n",
      "jupyterlab_server         2.27.2\n",
      "jupyterlab_widgets        3.0.11\n",
      "kiwisolver                1.4.5\n",
      "langchain                 0.2.1\n",
      "langchain-community       0.2.1\n",
      "langchain-core            0.2.3\n",
      "langchain-text-splitters  0.2.0\n",
      "langsmith                 0.1.69\n",
      "llamafactory              0.7.2.dev0     D:\\code\\LLaMA-Factory\n",
      "lxml                      5.2.2\n",
      "markdown-it-py            3.0.0\n",
      "MarkupSafe                2.1.5\n",
      "marshmallow               3.21.2\n",
      "matplotlib                3.9.0\n",
      "matplotlib-inline         0.1.7\n",
      "mdurl                     0.1.2\n",
      "mistune                   3.0.2\n",
      "mkl                       2021.4.0\n",
      "mpmath                    1.3.0\n",
      "multidict                 6.0.5\n",
      "multiprocess              0.70.16\n",
      "mypy-extensions           1.0.0\n",
      "nbclient                  0.10.0\n",
      "nbconvert                 7.16.4\n",
      "nbformat                  5.10.4\n",
      "nest-asyncio              1.6.0\n",
      "networkx                  3.2.1\n",
      "nltk                      3.8.1\n",
      "notebook                  7.2.1\n",
      "notebook_shim             0.2.4\n",
      "numpy                     1.26.3\n",
      "openai                    1.32.0\n",
      "orjson                    3.10.3\n",
      "overrides                 7.7.0\n",
      "packaging                 23.2\n",
      "pandas                    2.2.2\n",
      "pandocfilters             1.5.1\n",
      "parso                     0.8.4\n",
      "peft                      0.11.1\n",
      "pillow                    10.2.0\n",
      "pip                       24.0\n",
      "platformdirs              4.2.2\n",
      "prometheus_client         0.20.0\n",
      "prompt_toolkit            3.0.45\n",
      "protobuf                  4.25.3\n",
      "psutil                    5.9.8\n",
      "pure-eval                 0.2.2\n",
      "pyarrow                   16.1.0\n",
      "pyarrow-hotfix            0.6\n",
      "pycparser                 2.22\n",
      "pydantic                  2.7.1\n",
      "pydantic_core             2.18.2\n",
      "pydeck                    0.9.1\n",
      "pydub                     0.25.1\n",
      "Pygments                  2.18.0\n",
      "PyJWT                     2.8.0\n",
      "PyMuPDF                   1.24.5\n",
      "PyMuPDFb                  1.24.3\n",
      "pyparsing                 3.1.2\n",
      "python-dateutil           2.9.0.post0\n",
      "python-docx               1.1.2\n",
      "python-dotenv             1.0.1\n",
      "python-json-logger        2.0.7\n",
      "python-multipart          0.0.9\n",
      "python-pptx               0.6.23\n",
      "pytz                      2024.1\n",
      "pywin32                   306\n",
      "pywinpty                  2.0.13\n",
      "PyYAML                    6.0.1\n",
      "pyzmq                     26.0.3\n",
      "qtconsole                 5.5.2\n",
      "QtPy                      2.4.1\n",
      "referencing               0.35.1\n",
      "regex                     2024.5.15\n",
      "requests                  2.32.2\n",
      "rfc3339-validator         0.1.4\n",
      "rfc3986                   1.5.0\n",
      "rfc3986-validator         0.1.1\n",
      "rich                      13.7.1\n",
      "rouge-chinese             1.0.3\n",
      "rpds-py                   0.18.1\n",
      "ruff                      0.4.5\n",
      "safetensors               0.4.3\n",
      "scikit-learn              1.5.0\n",
      "scipy                     1.13.1\n",
      "semantic-version          2.10.0\n",
      "Send2Trash                1.8.3\n",
      "sentence-transformers     3.0.0\n",
      "sentencepiece             0.2.0\n",
      "setuptools                69.5.1\n",
      "shellingham               1.5.4\n",
      "shtab                     1.7.1\n",
      "six                       1.16.0\n",
      "smmap                     5.0.1\n",
      "sniffio                   1.3.1\n",
      "soupsieve                 2.5\n",
      "SQLAlchemy                2.0.30\n",
      "sse-starlette             2.1.0\n",
      "stack-data                0.6.3\n",
      "starlette                 0.37.2\n",
      "streamlit                 1.35.0\n",
      "sympy                     1.12\n",
      "tbb                       2021.11.0\n",
      "tenacity                  8.3.0\n",
      "termcolor                 2.4.0\n",
      "terminado                 0.18.1\n",
      "threadpoolctl             3.5.0\n",
      "tiktoken                  0.7.0\n",
      "timm                      1.0.3\n",
      "tinycss2                  1.3.0\n",
      "tokenizers                0.19.1\n",
      "toml                      0.10.2\n",
      "tomli                     2.0.1\n",
      "tomlkit                   0.12.0\n",
      "toolz                     0.12.1\n",
      "torch                     2.3.0+cu121\n",
      "torchaudio                2.3.0+cu121\n",
      "torchvision               0.18.0+cu121\n",
      "tornado                   6.4\n",
      "tqdm                      4.66.4\n",
      "traitlets                 5.14.3\n",
      "transformers              4.40.0\n",
      "trl                       0.8.6\n",
      "typer                     0.12.3\n",
      "types-python-dateutil     2.9.0.20240316\n",
      "typing_extensions         4.9.0\n",
      "typing-inspect            0.9.0\n",
      "tyro                      0.8.4\n",
      "tzdata                    2024.1\n",
      "ujson                     5.10.0\n",
      "uri-template              1.3.0\n",
      "urllib3                   2.2.1\n",
      "uvicorn                   0.29.0\n",
      "watchdog                  4.0.1\n",
      "watchfiles                0.21.0\n",
      "wcwidth                   0.2.13\n",
      "webcolors                 24.6.0\n",
      "webencodings              0.5.1\n",
      "websocket-client          1.8.0\n",
      "websockets                11.0.3\n",
      "wheel                     0.43.0\n",
      "widgetsnbextension        4.0.11\n",
      "XlsxWriter                3.2.0\n",
      "xxhash                    3.4.1\n",
      "yarl                      1.9.4\n",
      "zhipuai                   2.1.0.20240521\n"
     ]
    }
   ],
   "source": [
    "!pip list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b3d769fe-2e81-4fea-b4c3-460e2eef1abd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import necessary libraries\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "from pylab import rcParams\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import rc\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import confusion_matrix, classification_report\n",
    "from collections import defaultdict\n",
    "from textwrap import wrap\n",
    "\n",
    "# Torch ML libraries\n",
    "import transformers\n",
    "from transformers import BertModel, BertTokenizer, AdamW, get_linear_schedule_with_warmup\n",
    "import torch\n",
    "from torch import nn, optim\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "# Misc.\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings('ignore')\n",
    "import datetime\n",
    "\n",
    "# 获得计算机当前时间\n",
    "starttime = datetime.datetime.now()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3b04a872-77e2-4438-ad98-171d06402dab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set intial variables and constants\n",
    "# % config InlineBackend.figure_format='retina'\n",
    "\n",
    "# Graph Designs\n",
    "sns.set(style='whitegrid', palette='muted', font_scale=1.2)\n",
    "HAPPY_COLORS_PALETTE = [\"#01BEFE\", \"#FFDD00\", \"#FF7D00\", \"#FF006D\", \"#ADFF02\", \"#8F00FF\"]\n",
    "sns.set_palette(sns.color_palette(HAPPY_COLORS_PALETTE))\n",
    "rcParams['figure.figsize'] = 12, 8\n",
    "\n",
    "# Random seed for reproducibilty\n",
    "RANDOM_SEED = 42\n",
    "np.random.seed(RANDOM_SEED)\n",
    "torch.manual_seed(RANDOM_SEED)\n",
    "\n",
    "# Set GPU\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "7a9e4dd3-2300-4445-b84e-331f1d3cf226",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(12495, 12)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('reviews.csv')\n",
    "df.shape\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "bbdef7ed-f04f-47ff-a2e8-19467b142b03",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>reviewId</th>\n",
       "      <th>userName</th>\n",
       "      <th>userImage</th>\n",
       "      <th>content</th>\n",
       "      <th>score</th>\n",
       "      <th>thumbsUpCount</th>\n",
       "      <th>reviewCreatedVersion</th>\n",
       "      <th>at</th>\n",
       "      <th>replyContent</th>\n",
       "      <th>repliedAt</th>\n",
       "      <th>sortOrder</th>\n",
       "      <th>appId</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>gp:AOqpTOEhZuqSqqWnaKRgv-9ABYdajFUB0WugPGh-SG-...</td>\n",
       "      <td>Eric Tie</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>I cannot open the app anymore</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>5.4.0.6</td>\n",
       "      <td>2020-10-27 21:24:41</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.anydo</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>gp:AOqpTOH0WP4IQKBZ2LrdNmFy_YmpPCVrV3diEU9KGm3...</td>\n",
       "      <td>john alpha</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>I have been begging for a refund from this app...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2020-10-27 14:03:28</td>\n",
       "      <td>Please note that from checking our records, yo...</td>\n",
       "      <td>2020-10-27 15:05:52</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.anydo</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>gp:AOqpTOEMCkJB8Iq1p-r9dPwnSYadA5BkPWTf32Z1azu...</td>\n",
       "      <td>Sudhakar .S</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>Very costly for the premium version (approx In...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2020-10-27 08:18:40</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.anydo</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>gp:AOqpTOGFrUWuKGycpje8kszj3uwHN6tU_fd4gLVFy9z...</td>\n",
       "      <td>SKGflorida@bellsouth.net DAVID S</td>\n",
       "      <td>https://play-lh.googleusercontent.com/-75aK0WF...</td>\n",
       "      <td>Used to keep me organized, but all the 2020 UP...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2020-10-26 13:28:07</td>\n",
       "      <td>What do you find troublesome about the update?...</td>\n",
       "      <td>2020-10-26 14:58:29</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.anydo</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>gp:AOqpTOHls7DW8wmDFzTkHwxuqFkdNQtKHmO6Pt9jhZE...</td>\n",
       "      <td>Louann Stoker</td>\n",
       "      <td>https://play-lh.googleusercontent.com/-pBcY_Z-...</td>\n",
       "      <td>Dan Birthday Oct 28</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>5.6.0.7</td>\n",
       "      <td>2020-10-26 06:10:50</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.anydo</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12490</th>\n",
       "      <td>gp:AOqpTOEQPqib7pb6vFyjMY9JEfsMs_u8WCdqg6mbcar...</td>\n",
       "      <td>Mildred Olima</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>I really like the planner, it helps me achieve...</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>4.5.4</td>\n",
       "      <td>2018-12-21 00:13:09</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.appxy.planner</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12491</th>\n",
       "      <td>gp:AOqpTOE1KKOOVVKUfhAfXQs2NfJpoywfucrJCMK3Hmu...</td>\n",
       "      <td>Roaring Grizzly Bear</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>😁****😁</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2018-12-12 21:52:56</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.appxy.planner</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12492</th>\n",
       "      <td>gp:AOqpTOFEn5UgYYggqiHKauDJVLLN8-16nk1AfZbEhkj...</td>\n",
       "      <td>amirbadang</td>\n",
       "      <td>https://play-lh.googleusercontent.com/-CM2FcrU...</td>\n",
       "      <td>Very useful apps. You must try it</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>4.5.4</td>\n",
       "      <td>2018-12-11 15:49:43</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.appxy.planner</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12493</th>\n",
       "      <td>gp:AOqpTOHOH6YdYLR91qZdYpeIVkMI-LeAE0EwYgrctid...</td>\n",
       "      <td>Emma Stebbins</td>\n",
       "      <td>https://play-lh.googleusercontent.com/-oCj6g6k...</td>\n",
       "      <td>Would pay for this if there were even more add...</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>4.5.4</td>\n",
       "      <td>2018-12-06 04:59:26</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.appxy.planner</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12494</th>\n",
       "      <td>gp:AOqpTOFuJtS1McUdEZuLCnRn7k-UUcGNml7XqxKTSk2...</td>\n",
       "      <td>DAVOR SPASENOSKI</td>\n",
       "      <td>https://play-lh.googleusercontent.com/a-/AOh14...</td>\n",
       "      <td>Sooow good</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>4.5.4</td>\n",
       "      <td>2018-11-26 01:19:13</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>newest</td>\n",
       "      <td>com.appxy.planner</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>12495 rows × 12 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                reviewId  \\\n",
       "0      gp:AOqpTOEhZuqSqqWnaKRgv-9ABYdajFUB0WugPGh-SG-...   \n",
       "1      gp:AOqpTOH0WP4IQKBZ2LrdNmFy_YmpPCVrV3diEU9KGm3...   \n",
       "2      gp:AOqpTOEMCkJB8Iq1p-r9dPwnSYadA5BkPWTf32Z1azu...   \n",
       "3      gp:AOqpTOGFrUWuKGycpje8kszj3uwHN6tU_fd4gLVFy9z...   \n",
       "4      gp:AOqpTOHls7DW8wmDFzTkHwxuqFkdNQtKHmO6Pt9jhZE...   \n",
       "...                                                  ...   \n",
       "12490  gp:AOqpTOEQPqib7pb6vFyjMY9JEfsMs_u8WCdqg6mbcar...   \n",
       "12491  gp:AOqpTOE1KKOOVVKUfhAfXQs2NfJpoywfucrJCMK3Hmu...   \n",
       "12492  gp:AOqpTOFEn5UgYYggqiHKauDJVLLN8-16nk1AfZbEhkj...   \n",
       "12493  gp:AOqpTOHOH6YdYLR91qZdYpeIVkMI-LeAE0EwYgrctid...   \n",
       "12494  gp:AOqpTOFuJtS1McUdEZuLCnRn7k-UUcGNml7XqxKTSk2...   \n",
       "\n",
       "                               userName  \\\n",
       "0                              Eric Tie   \n",
       "1                            john alpha   \n",
       "2                           Sudhakar .S   \n",
       "3      SKGflorida@bellsouth.net DAVID S   \n",
       "4                         Louann Stoker   \n",
       "...                                 ...   \n",
       "12490                     Mildred Olima   \n",
       "12491              Roaring Grizzly Bear   \n",
       "12492                        amirbadang   \n",
       "12493                     Emma Stebbins   \n",
       "12494                  DAVOR SPASENOSKI   \n",
       "\n",
       "                                               userImage  \\\n",
       "0      https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "1      https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "2      https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "3      https://play-lh.googleusercontent.com/-75aK0WF...   \n",
       "4      https://play-lh.googleusercontent.com/-pBcY_Z-...   \n",
       "...                                                  ...   \n",
       "12490  https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "12491  https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "12492  https://play-lh.googleusercontent.com/-CM2FcrU...   \n",
       "12493  https://play-lh.googleusercontent.com/-oCj6g6k...   \n",
       "12494  https://play-lh.googleusercontent.com/a-/AOh14...   \n",
       "\n",
       "                                                 content  score  \\\n",
       "0                          I cannot open the app anymore      1   \n",
       "1      I have been begging for a refund from this app...      1   \n",
       "2      Very costly for the premium version (approx In...      1   \n",
       "3      Used to keep me organized, but all the 2020 UP...      1   \n",
       "4                                    Dan Birthday Oct 28      1   \n",
       "...                                                  ...    ...   \n",
       "12490  I really like the planner, it helps me achieve...      5   \n",
       "12491                                             😁****😁      5   \n",
       "12492                  Very useful apps. You must try it      5   \n",
       "12493  Would pay for this if there were even more add...      5   \n",
       "12494                                         Sooow good      5   \n",
       "\n",
       "       thumbsUpCount reviewCreatedVersion                   at  \\\n",
       "0                  0              5.4.0.6  2020-10-27 21:24:41   \n",
       "1                  0                  NaN  2020-10-27 14:03:28   \n",
       "2                  0                  NaN  2020-10-27 08:18:40   \n",
       "3                  0                  NaN  2020-10-26 13:28:07   \n",
       "4                  0              5.6.0.7  2020-10-26 06:10:50   \n",
       "...              ...                  ...                  ...   \n",
       "12490              0                4.5.4  2018-12-21 00:13:09   \n",
       "12491              0                  NaN  2018-12-12 21:52:56   \n",
       "12492              0                4.5.4  2018-12-11 15:49:43   \n",
       "12493              0                4.5.4  2018-12-06 04:59:26   \n",
       "12494              0                4.5.4  2018-11-26 01:19:13   \n",
       "\n",
       "                                            replyContent            repliedAt  \\\n",
       "0                                                    NaN                  NaN   \n",
       "1      Please note that from checking our records, yo...  2020-10-27 15:05:52   \n",
       "2                                                    NaN                  NaN   \n",
       "3      What do you find troublesome about the update?...  2020-10-26 14:58:29   \n",
       "4                                                    NaN                  NaN   \n",
       "...                                                  ...                  ...   \n",
       "12490                                                NaN                  NaN   \n",
       "12491                                                NaN                  NaN   \n",
       "12492                                                NaN                  NaN   \n",
       "12493                                                NaN                  NaN   \n",
       "12494                                                NaN                  NaN   \n",
       "\n",
       "      sortOrder              appId  \n",
       "0        newest          com.anydo  \n",
       "1        newest          com.anydo  \n",
       "2        newest          com.anydo  \n",
       "3        newest          com.anydo  \n",
       "4        newest          com.anydo  \n",
       "...         ...                ...  \n",
       "12490    newest  com.appxy.planner  \n",
       "12491    newest  com.appxy.planner  \n",
       "12492    newest  com.appxy.planner  \n",
       "12493    newest  com.appxy.planner  \n",
       "12494    newest  com.appxy.planner  \n",
       "\n",
       "[12495 rows x 12 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a28c873b-30bc-43e6-a815-6903e286253c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "reviewId                   0\n",
       "userName                   0\n",
       "userImage                  0\n",
       "content                    0\n",
       "score                      0\n",
       "thumbsUpCount              0\n",
       "reviewCreatedVersion    2162\n",
       "at                         0\n",
       "replyContent            6677\n",
       "repliedAt               6677\n",
       "sortOrder                  0\n",
       "appId                      0\n",
       "dtype: int64"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.isnull().sum()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "053823d4-961f-4a63-bfbd-7399be28ace1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function to convert score to sentiment\n",
    "def to_sentiment(rating):\n",
    "    rating = int(rating)\n",
    "\n",
    "    # Convert to class\n",
    "    if rating <= 2:\n",
    "        return 0\n",
    "    elif rating == 3:\n",
    "        return 1\n",
    "    else:\n",
    "        return 2\n",
    "\n",
    "\n",
    "# Apply to the dataset\n",
    "df['sentiment'] = df.score.apply(to_sentiment)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "47941db2-091e-4b80-a5a6-cc7dfcba952a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4850\n",
      "1991\n",
      "5654\n"
     ]
    }
   ],
   "source": [
    "# Plot the distribution\n",
    "class_names = ['negative', 'neutral', 'positive']\n",
    "# print(df.sentiment)\n",
    "# ax = sns.countplot(df.sentiment)\n",
    "# plt.xlabel('review sentiment')\n",
    "# ax.set_xticklabels(class_names)\n",
    "print(len(df[df['sentiment']==0]))\n",
    "print(len(df[df['sentiment']==1]))\n",
    "print(len(df[df['sentiment']==2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e9c22c90-8342-46e6-b1e3-fb901bbec8d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set the model name\n",
    "MODEL_NAME = 'bert-base-cased'\n",
    "\n",
    "# Build a BERT based tokenizer\n",
    "tokenizer = BertTokenizer.from_pretrained(MODEL_NAME)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f2d6702b-d3c6-4f88-bbb5-b90a1643ee24",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SEP] 102\n",
      "[CLS] 101\n",
      "[PAD] 0\n",
      "[UNK] 100\n"
     ]
    }
   ],
   "source": [
    "# Some of the common BERT tokens\n",
    "print(tokenizer.sep_token, tokenizer.sep_token_id)  # marker for ending of a sentence\n",
    "print(tokenizer.cls_token, tokenizer.cls_token_id)  # start of each sentence, so BERT knows we’re doing classification\n",
    "print(tokenizer.pad_token, tokenizer.pad_token_id)  # special token for padding\n",
    "print(tokenizer.unk_token, tokenizer.unk_token_id)  # tokens not found in training set\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "811e4380-70b2-4e26-a527-d2a290b59cd5",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Truncation was not explicitly activated but `max_length` is provided a specific value, please use `truncation=True` to explicitly truncate examples to max length. Defaulting to 'longest_first' truncation strategy. If you encode pairs of sequences (GLUE-style) with the tokenizer you can select this strategy more precisely by providing a specific strategy to `truncation`.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Text(0.5, 0, 'Token count')"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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X2by5Mm89957PPjgg3zxi19k/vz55OXlHdoH/Jj6KRD7k5SURHnX3mzeVk1pdXykBJnJEbbVJFNSvIWamppYl6M4c7A+LbVH9mslGvu0EpH9WomoLfp1/SL9BxJXIUEYhgAHTDeak3wcSrtly5bxrW99i/T0dGbOnNnwS+vSpQs33XRTwzaMAOeddx5nnnkml19+OTNnzuTnP/95i2qpN3DgwIOud1BYk0xOUkh5fGQEpEegZ7eAvjnZsS5FcaSsrIx169Y1q09L7YX9WonGPq1EZL9WImqrfr127dpmnRdXIUH9egJNfetfXl4OQFZW1n7b1p/T3HbPPPMMt9xyC0lJScyaNWufKQT9+/dnypQpjdocf/zxjBw5smEBxMORkZHRaA2Fj0spD0lJhdo4CQlSIpCSApnpB0+g1PE0p09L7Y39WonGPq1EZL9WImrtft3cL9zjauHCfv36AbB169ZG79UvWNjUegUAffv2PaR2CxYs4Jvf/Capqak89NBDnH766c2us3v37pSXl1MbL3fukiRJkiS1grgKCTp37kxubi6rVq1q9N6qVavo06cPvXr1arLtkCFDWLt2baPRBPXXOumkkxpee+KJJ/je975HdnY2c+fOZdSoUY2u96tf/Yrzzz+fNWvWNHrvvffeo2/fvkQicfXrkyRJkiTpsMTdXe5FF13EihUr9gkK1qxZw/Lly7n00ksP2K6yspL58+c3vFZaWsrChQsZNmwYubm5AKxevbohIPjlL3/JiSee2OT1+vfvz4YNG/jlL3+5z+tPP/00a9as4XOf+9zhfExJkiRJkuJOXK1JAFBQUMDixYspKCigoKCASCTC7NmzycnJoaCgAIBt27bx4osvkpuby8knnwxAfn4++fn53H333RQVFTFo0CAWLFjApk2buOuuuxquP3PmTKqqqsjPz2flypWsXLlyn5/fr18/Ro0axdlnn83555/P448/zq5duzjttNN45513ePzxxznhhBP4yle+cuR+KZIkSZIkHQFxFxJkZ2czb9487rzzTmbNmkVqaiqnnnoq06ZNo3v37kB0e8Jp06Yxbty4hpAA4N5772XmzJksWbKEsrIy8vLyePjhh/eZTvDyyy8DsGTJEpYsWdLo519yySUN58+cOZNZs2axZMkSnn32WXr06ME111zDN77xDRdGkSRJkiQlnLgLCQAG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",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Store length of each review\n",
    "token_lens = []\n",
    "# Iterate through the content slide\n",
    "for txt in df.content:\n",
    "    tokens = tokenizer.encode(txt, max_length=512)\n",
    "    token_lens.append(len(tokens))\n",
    "\n",
    "# plot the distribution of review lengths\n",
    "sns.distplot(token_lens)\n",
    "plt.xlim([0, 256])\n",
    "plt.xlabel('Token count')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "806dc06d-8a91-4943-baad-8da35bc0cc60",
   "metadata": {},
   "outputs": [],
   "source": [
    "MAX_LEN = 160\n",
    "\n",
    "class GPReviewDataset(Dataset):\n",
    "    # Constructor Function\n",
    "    def __init__(self, reviews, targets, tokenizer, max_len):\n",
    "        self.reviews = reviews\n",
    "        self.targets = targets\n",
    "        self.tokenizer = tokenizer\n",
    "        self.max_len = max_len\n",
    "\n",
    "    # Length magic method\n",
    "    def __len__(self):\n",
    "        return len(self.reviews)\n",
    "\n",
    "    # get item magic method\n",
    "    def __getitem__(self, item):\n",
    "        review = str(self.reviews[item])\n",
    "        target = self.targets[item]\n",
    "\n",
    "        # Encoded format to be returned\n",
    "        encoding = self.tokenizer.encode_plus(\n",
    "            review,\n",
    "            add_special_tokens=True,\n",
    "            max_length=self.max_len,\n",
    "            return_token_type_ids=False,\n",
    "            pad_to_max_length=True,\n",
    "            return_attention_mask=True,\n",
    "            return_tensors='pt',\n",
    "        )\n",
    "\n",
    "        return {\n",
    "            'review_text': review,\n",
    "            'input_ids': encoding['input_ids'].flatten(),\n",
    "            'attention_mask': encoding['attention_mask'].flatten(),\n",
    "            'targets': torch.tensor(target, dtype=torch.long)\n",
    "        }\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "5f3d1e8b-6485-4345-bad1-d6f167387ea1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(9996, 13) (1249, 13) (1250, 13)\n"
     ]
    }
   ],
   "source": [
    "df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)\n",
    "df_val, df_test = train_test_split(df_test, test_size=0.5, random_state=42)\n",
    "\n",
    "print(df_train.shape, df_val.shape, df_test.shape)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "f08c5725-5564-420c-9c61-6c9144d78a3e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_data_loader(df, tokenizer, max_len, batch_size):\n",
    "    ds = GPReviewDataset(\n",
    "        reviews=df.content.to_numpy(),\n",
    "        targets=df.sentiment.to_numpy(),\n",
    "        tokenizer=tokenizer,\n",
    "        max_len=max_len\n",
    "    )\n",
    "\n",
    "    return DataLoader(\n",
    "        ds,\n",
    "        batch_size=batch_size,\n",
    "        num_workers=0\n",
    "    )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "18c2db09-b45e-4a4c-a996-915c26d6aac2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create train, test and val data loaders\n",
    "BATCH_SIZE = 32\n",
    "train_data_loader = create_data_loader(df_train, tokenizer, MAX_LEN, BATCH_SIZE)\n",
    "val_data_loader = create_data_loader(df_val, tokenizer, MAX_LEN, BATCH_SIZE)\n",
    "test_data_loader = create_data_loader(df_test, tokenizer, MAX_LEN, BATCH_SIZE)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "4af9de1b-df26-485a-a0d6-9cf34a1f35e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['review_text', 'input_ids', 'attention_mask', 'targets'])\n",
      "torch.Size([32, 160])\n",
      "torch.Size([32, 160])\n",
      "torch.Size([32])\n"
     ]
    }
   ],
   "source": [
    "# Examples\n",
    "data = next(iter(train_data_loader))\n",
    "print(data.keys())\n",
    "print(data['input_ids'].shape)\n",
    "print(data['attention_mask'].shape)\n",
    "print(data['targets'].shape)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c1e96590-9aab-476a-a86d-419a8d60e6a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load the basic BERT model\n",
    "bert_model = BertModel.from_pretrained(MODEL_NAME)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "56c9de68-fb80-4d78-9197-7958b096c457",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Build the Sentiment Classifier class\n",
    "class SentimentClassifier(nn.Module):\n",
    "\n",
    "    # Constructor class\n",
    "    def __init__(self, n_classes):\n",
    "        super(SentimentClassifier, self).__init__()\n",
    "        self.bert = BertModel.from_pretrained(MODEL_NAME)\n",
    "        self.drop = nn.Dropout(p=0.3)\n",
    "        self.out = nn.Linear(self.bert.config.hidden_size, n_classes)\n",
    "\n",
    "    # Forward propagaion class\n",
    "    def forward(self, input_ids, attention_mask):\n",
    "        _, pooled_output = self.bert(\n",
    "            input_ids=input_ids,\n",
    "            attention_mask=attention_mask,\n",
    "            return_dict=False\n",
    "        )\n",
    "        #  Add a dropout layer\n",
    "        output = self.drop(pooled_output)\n",
    "        return self.out(output)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "2af95357-53a3-4cd8-91d1-da740ab6565c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda')"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Instantiate the model and move to classifier\n",
    "model = SentimentClassifier(len(class_names))\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model = model.to(device)\n",
    "device\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "7e23539c-1de1-45f1-8bb0-381b5a40e43b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "768\n"
     ]
    }
   ],
   "source": [
    "# Number of hidden units\n",
    "print(bert_model.config.hidden_size)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "f1a185fc-4586-4028-896b-032ce144fced",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Number of iterations\n",
    "EPOCHS = 10\n",
    "\n",
    "# Optimizer Adam\n",
    "optimizer = AdamW(model.parameters(), lr=2e-5, correct_bias=False)\n",
    "\n",
    "total_steps = len(train_data_loader) * EPOCHS\n",
    "\n",
    "scheduler = get_linear_schedule_with_warmup(\n",
    "    optimizer,\n",
    "    num_warmup_steps=0,\n",
    "    num_training_steps=total_steps\n",
    ")\n",
    "\n",
    "# Set the loss function\n",
    "loss_fn = nn.CrossEntropyLoss().to(device)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "0b2cd7b0-05a6-4945-8af2-10e5418e5c86",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "from torch.cuda.amp import GradScaler, autocast\n",
    "\n",
    "scaler = GradScaler()\n",
    "\n",
    "\n",
    "def train_epoch(model, data_loader, loss_fn, optimizer, device, scheduler, n_examples):\n",
    "    model = model.train()\n",
    "    losses = []\n",
    "    correct_predictions = 0\n",
    "\n",
    "    for d in data_loader:\n",
    "        input_ids = d[\"input_ids\"].to(device)\n",
    "        attention_mask = d[\"attention_mask\"].to(device)\n",
    "        targets = d[\"targets\"].to(device)\n",
    "\n",
    "\n",
    "        # Gradient Descent\n",
    "        nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n",
    "\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        with autocast():\n",
    "            #一定要把模型设置在fp16模型中输出\n",
    "            outputs = model(\n",
    "            input_ids=input_ids,\n",
    "            attention_mask=attention_mask)\n",
    "            \n",
    "            _, preds = torch.max(outputs, dim=1)\n",
    "            loss = loss_fn(outputs, targets)\n",
    "            correct_predictions += torch.sum(preds == targets)\n",
    "            losses.append(loss.item())\n",
    "\n",
    "        # Scales loss.  Calls backward() on scaled loss to create scaled gradients.\n",
    "        # Backward passes under autocast are not recommended.\n",
    "        # Backward ops run in the same dtype autocast chose for corresponding forward ops.\n",
    "        scaler.scale(loss).backward()\n",
    "\n",
    "        # scaler.step() first unscales the gradients of the optimizer's assigned params.\n",
    "        # If these gradients do not contain infs or NaNs, optimizer.step() is then called,\n",
    "        # otherwise, optimizer.step() is skipped.\n",
    "        scaler.step(optimizer)\n",
    "\n",
    "        # Updates the scale for next iteration.\n",
    "        scaler.update()\n",
    "\n",
    "    return correct_predictions.double() / n_examples, np.mean(losses)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "462964b9-1280-4929-b5c9-f36712cdd70e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def eval_model(model, data_loader, loss_fn, device, n_examples):\n",
    "    model = model.eval()\n",
    "\n",
    "    losses = []\n",
    "    correct_predictions = 0\n",
    "\n",
    "    with torch.no_grad():\n",
    "        for d in data_loader:\n",
    "            input_ids = d[\"input_ids\"].to(device)\n",
    "            attention_mask = d[\"attention_mask\"].to(device)\n",
    "            targets = d[\"targets\"].to(device)\n",
    "\n",
    "            # Get model ouptuts\n",
    "            outputs = model(\n",
    "                input_ids=input_ids,\n",
    "                attention_mask=attention_mask\n",
    "            )\n",
    "\n",
    "            _, preds = torch.max(outputs, dim=1)\n",
    "            loss = loss_fn(outputs, targets)\n",
    "\n",
    "            correct_predictions += torch.sum(preds == targets)\n",
    "            losses.append(loss.item())\n",
    "\n",
    "    return correct_predictions.double() / n_examples, np.mean(losses)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "d5b348ee-9df7-4228-ab18-dd9627b6ec72",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "----------\n",
      "Train loss 0.7416254019204039 accuracy 0.694077631052421\n",
      "Val   loss 0.6154848650097847 accuracy 0.7566052842273818\n",
      "\n",
      "Epoch 2/10\n",
      "----------\n",
      "Train loss 0.5435252564783675 accuracy 0.7854141656662665\n",
      "Val   loss 0.611801727861166 accuracy 0.7590072057646117\n",
      "\n",
      "Epoch 3/10\n",
      "----------\n",
      "Train loss 0.4178346009871449 accuracy 0.8367346938775511\n",
      "Val   loss 0.6699942462146282 accuracy 0.7598078462770216\n",
      "\n",
      "Epoch 4/10\n",
      "----------\n",
      "Train loss 0.29979248352039356 accuracy 0.8900560224089636\n",
      "Val   loss 0.8747110791504383 accuracy 0.7349879903923138\n",
      "\n",
      "Epoch 5/10\n",
      "----------\n",
      "Train loss 0.23287898463943896 accuracy 0.9162665066026411\n",
      "Val   loss 0.8928058827295899 accuracy 0.7261809447558046\n",
      "\n",
      "Epoch 6/10\n",
      "----------\n",
      "Train loss 0.14715991841670803 accuracy 0.9508803521408564\n",
      "Val   loss 1.0847721859812736 accuracy 0.7285828662930344\n",
      "\n",
      "Epoch 7/10\n",
      "----------\n",
      "Train loss 0.11242074700899589 accuracy 0.965186074429772\n",
      "Val   loss 1.1688420616090298 accuracy 0.7285828662930344\n",
      "\n",
      "Epoch 8/10\n",
      "----------\n",
      "Train loss 0.09269447088503419 accuracy 0.9702881152460985\n",
      "Val   loss 1.1067617528140545 accuracy 0.7445956765412329\n",
      "\n",
      "Epoch 9/10\n",
      "----------\n",
      "Train loss 0.08419372173496328 accuracy 0.9719887955182074\n",
      "Val   loss 1.1997741363942622 accuracy 0.7429943955164131\n",
      "\n",
      "Epoch 10/10\n",
      "----------\n",
      "Train loss 0.07874595423856863 accuracy 0.974389755902361\n",
      "Val   loss 1.2620356969535351 accuracy 0.733386709367494\n",
      "\n",
      "1995\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "history = defaultdict(list)\n",
    "best_accuracy = 0\n",
    "\n",
    "for epoch in range(EPOCHS):\n",
    "\n",
    "    # Show details\n",
    "    print(f\"Epoch {epoch + 1}/{EPOCHS}\")\n",
    "    print(\"-\" * 10)\n",
    "\n",
    "    train_acc, train_loss = train_epoch(\n",
    "        model,\n",
    "        train_data_loader,\n",
    "        loss_fn,\n",
    "        optimizer,\n",
    "        device,\n",
    "        scheduler,\n",
    "        len(df_train)\n",
    "    )\n",
    "\n",
    "    print(f\"Train loss {train_loss} accuracy {train_acc}\")\n",
    "\n",
    "    # Get model performance (accuracy and loss)\n",
    "    val_acc, val_loss = eval_model(\n",
    "        model,\n",
    "        val_data_loader,\n",
    "        loss_fn,\n",
    "        device,\n",
    "        len(df_val)\n",
    "    )\n",
    "\n",
    "    print(f\"Val   loss {val_loss} accuracy {val_acc}\")\n",
    "    print()\n",
    "\n",
    "    history['train_acc'].append(train_acc)\n",
    "    history['train_loss'].append(train_loss)\n",
    "    history['val_acc'].append(val_acc)\n",
    "    history['val_loss'].append(val_loss)\n",
    "\n",
    "    # If we beat prev performance\n",
    "    if val_acc > best_accuracy:\n",
    "        torch.save(model.state_dict(), 'best_model_state.bin')\n",
    "        best_accuracy = val_acc\n",
    "# 获取过段时间后的时间\n",
    "endtime = datetime.datetime.now()\n",
    "\n",
    "print((endtime - starttime).seconds)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "849d2448-36d4-4ae7-b670-5f299cd42d49",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "    negative       0.74      0.80      0.77       480\n",
      "     neutral       0.37      0.23      0.28       216\n",
      "    positive       0.81      0.88      0.84       554\n",
      "\n",
      "    accuracy                           0.74      1250\n",
      "   macro avg       0.64      0.63      0.63      1250\n",
      "weighted avg       0.71      0.74      0.72      1250\n",
      "\n",
      "Review text: I love completing my todos! Best app ever!!!\n",
      "Sentiment  : positive\n"
     ]
    },
    {
     "data": {
      "image/png": "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QURE5G4UgIuISLnh7OxMeHg4J0+eZMWKFcXe+/zzz5k9ezaJiYm4ubnh5OTE888/z5kzZ4rlzc/PZ+7cub9aVkBAAI899hhbtmwpFgTn5+ezcuVKHBwcbMeIFW2yVlBQYMsXFRWFYRhMnTrVtn4Z4OLFi0yePJl3333XNppbtEnczJkzi91j+fLlXLp06VfrWqlSJZYuXcr8+fOLlZWfn09WVhYmkwlPT8/76r/7dac++CM8DG0QERG5G01BFxGRcmXs2LEcOnSIWbNmsWfPHpo3b05mZiYffvghjo6OTJ8+3baT+IgRI9i/fz8zZ84kLS2N+vXrs3//fq5cuVJiffntiu71yiuvEBMTwzPPPIOHhwepqamcPn2a8ePH284tL/r/zJkzCQwMZOjQoXTv3p2PPvqInTt38u2339K+fXssFgspKSlcuXKFkSNH4uXlBUB4eDg7d+5kx44dpKen065dO06ePMmBAweoU6fOr+7U7enpyV//+ldWrFjB888/z9NPP429vT379u3j1KlTxMbG2tay30//3Y9q1aphMpn4/PPPmTFjBs888wxPPvnkfd/nt3gY2iAiInInGgEXEZFypXr16mzcuJEBAwaQmZnJ6tWr+de//kVoaCgbN26kTZs2trxubm6sX7+emJgYvv32W+Lj46lRowYrV6781c2+4NZu5+vXr6ddu3bs3buXtWvX4uLiwqxZs+jfv78tX69evQgKCuLIkSOsXr2a69evY2dnx4IFC5g4cSIuLi5s2rSJlJQUGjRowD/+8Q9efvnlYmXNmzePUaNGkZ+fz/r168nKymLRokXFjuS6l9GjRzNlyhSqVKlCcnIyGzdupHLlysycOZNXX331d/Xf/TCZTEyaNAk3NzfWrVv3qzu3/y8ehjaIiIjciZ2h7UFFRERERERE/nAaARcREREREREpBQrARUREREREREqBAnARERERERGRUqAAXERERERERKQUKAAXERERERERKQUKwEVERERERERKgQJwERERERERkVKgAFxERERERESkFCgAFxERERERESkFCsBFRERERERESoECcBEREREREZFSoABcREREREREpBQoABcREREREREpBf8Pcd/GbCynh5sAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1200x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# 读取训练好的模型\n",
    "model.load_state_dict(torch.load('best_model_state.bin'))\n",
    "\n",
    "test_acc, _ = eval_model(\n",
    "    model,\n",
    "    test_data_loader,\n",
    "    loss_fn,\n",
    "    device,\n",
    "    len(df_test)\n",
    ")\n",
    "\n",
    "test_acc.item()\n",
    "\n",
    "\n",
    "def get_predictions(model, data_loader):\n",
    "    model = model.eval()\n",
    "\n",
    "    review_texts = []\n",
    "    predictions = []\n",
    "    prediction_probs = []\n",
    "    real_values = []\n",
    "\n",
    "    with torch.no_grad():\n",
    "        for d in data_loader:\n",
    "            texts = d[\"review_text\"]\n",
    "            input_ids = d[\"input_ids\"].to(device)\n",
    "            attention_mask = d[\"attention_mask\"].to(device)\n",
    "            targets = d[\"targets\"].to(device)\n",
    "\n",
    "            # Get outouts\n",
    "            outputs = model(\n",
    "                input_ids=input_ids,\n",
    "                attention_mask=attention_mask\n",
    "            )\n",
    "            _, preds = torch.max(outputs, dim=1)\n",
    "\n",
    "            review_texts.extend(texts)\n",
    "            predictions.extend(preds)\n",
    "            prediction_probs.extend(outputs)\n",
    "            real_values.extend(targets)\n",
    "\n",
    "    predictions = torch.stack(predictions).cpu()\n",
    "    prediction_probs = torch.stack(prediction_probs).cpu()\n",
    "    real_values = torch.stack(real_values).cpu()\n",
    "\n",
    "    return review_texts, predictions, prediction_probs, real_values\n",
    "\n",
    "\n",
    "y_review_texts, y_pred, y_pred_probs, y_test = get_predictions(\n",
    "    model,\n",
    "    test_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_test, y_pred, target_names=class_names))\n",
    "\n",
    "\n",
    "def show_confusion_matrix(confusion_matrix):\n",
    "    hmap = sns.heatmap(confusion_matrix, annot=True, fmt=\"d\", cmap=\"Blues\")\n",
    "    hmap.yaxis.set_ticklabels(hmap.yaxis.get_ticklabels(), rotation=0, ha='right')\n",
    "    hmap.xaxis.set_ticklabels(hmap.xaxis.get_ticklabels(), rotation=30, ha='right')\n",
    "    plt.ylabel('True sentiment')\n",
    "    plt.xlabel('Predicted sentiment');\n",
    "\n",
    "\n",
    "cm = confusion_matrix(y_test, y_pred)\n",
    "df_cm = pd.DataFrame(cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_cm)\n",
    "\n",
    "review_text = \"I love completing my todos! Best app ever!!!\"\n",
    "encoded_review = tokenizer.encode_plus(\n",
    "    review_text,\n",
    "    max_length=MAX_LEN,\n",
    "    add_special_tokens=True,\n",
    "    return_token_type_ids=False,\n",
    "    pad_to_max_length=True,\n",
    "    return_attention_mask=True,\n",
    "    return_tensors='pt',\n",
    ")\n",
    "\n",
    "input_ids = encoded_review['input_ids'].to(device)\n",
    "attention_mask = encoded_review['attention_mask'].to(device)\n",
    "\n",
    "output = model(input_ids, attention_mask)\n",
    "_, prediction = torch.max(output, dim=1)\n",
    "\n",
    "print(f'Review text: {review_text}')\n",
    "print(f'Sentiment  : {class_names[prediction]}')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "05e5532a-9aea-47f3-a951-e5a56974adf0",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
